/*****************************************************************************
 *
 *              LCDControl.c -- LCD Display Driver
 *
 *****************************************************************************
 * FileName:        LCDControl.c
 *
 * Dependencies:    LCDControl.c
 *					Timer.c
 *
 * LCD Model:       NewHaven NHD-0420E2Z-NSW-BBW
 *
 * Author:          Sheng Chen and Eric DeYoung
 *
 * Date:            Nov 22, 2008
 *
 * Description:     NewHaven NHD-0420E2Z-NSW-BBW LCD Demonstration Program
 *
 *****************************************************************************/

#include <avr/io.h>
#include <string.h>
#include "timer.h"
#include "utility.h"

#define RS 5
#define RW 6
#define E 7
#define VC 3
#define BCKLT 4
#define UpArrow 4
#define DownArrow 5
#define Back 7
#define Enter 6
#define TemperatureSensor 1
#define BatteryVoltageSensor 2


void pulse_E(void) //Pulse Enable PIN
{
	PORTD |= _BV(E);
	delay_ns(1);
	PORTD &= ~_BV(E);
}

void LCD_Write(unsigned char var) //Write Character to LCD
{
	PORTD |= _BV(RS);
	delay_ns(1);

	PORTC = var;
	pulse_E();
}

void LCD_Print(char *text) //Print String on LCD
{
	int k;

	for(k=0;k<strlen(text); k++)
	{
		LCD_Write(text[k]);
	}
}


void Goto(unsigned char Position) //Go to any location on the LCD
{
	PORTD &= ~_BV(RS) & ~_BV(RW) & ~_BV(E); //Set RS, R/W, E to Low

	delay_ns(1);

	PORTC = _BV(7) | Position;

	pulse_E();
}


void busy_flag(void) //Busy Flag check
{
	unsigned char busyflag;

	DDRC &= ~0xFF; //Set RegC to input

	PORTD &= ~_BV(RS); //Set RS to Low

	PORTD |= _BV(RW); //Set R/W to R

	do{
		pulse_E();
		busyflag=(PINC & _BV(7));
		pulse_E();
	  } while (busyflag != 0);

	DDRC |= 0xFF;
}

void LCD_CLS(void)//Clear Screen
{
	PORTD &= ~_BV(RS) & ~_BV(RW) & ~_BV(E); //Set RS, R/W, E to Low

	delay_ns(1);

	PORTC = _BV(0); //Clear screen

	pulse_E();

	delay(20); //Wait 2 ms
}


void DebounceDelay(void)
{
	delay(195); //20 ms delay
	delay(195); //20 ms delay
	delay(195); //20 ms delay
}

void LCD_OFF(void)
{
	PORTD &= ~_BV(RS) & ~_BV(RW) & ~_BV(E); //Set RS, R/W, E to Low

	delay_ns(1); //Wait 100 ns

	PORTC = _BV(3); //Display OFF

	pulse_E();
}

void LCD_ON(void)
{
	PORTD &= ~_BV(RS) & ~_BV(RW) & ~_BV(E); //Set RS, R/W, E to Low

	delay_ns(1); //Wait 100 ns

	PORTC = _BV(3) | _BV(2); //Display ON

	pulse_E();
}

void CharacterGenerate(void)
{
	PORTD &= ~_BV(RS) & ~_BV(RW) & ~_BV(E); //Set RS, R/W, E to Low
	delay_ns(1);

	//Up Arrow
	PORTC = _BV(6); //Set CGRAM 0x00
	pulse_E();
	delay_ns(1);

	LCD_Write(0x04);  // .....*..
	LCD_Write(0x0E);  // ....***.
	LCD_Write(0x15);  // ...*.*.*
    LCD_Write(0x04);  // .....*..
    LCD_Write(0x04);  // .....*..
    LCD_Write(0x04);  // .....*..
	LCD_Write(0x04);  // .....*..
	LCD_Write(0x00);  // ........

	//Down Arrow
	PORTC = _BV(6) | _BV(3); //Set CGRAM 0x01
	pulse_E();
	delay_ns(1);

	LCD_Write(0x04); //.....*..
	LCD_Write(0x04); //.....*..
	LCD_Write(0x04); //.....*..
	LCD_Write(0x04); //.....*..
	LCD_Write(0x15); //...*.*.*
	LCD_Write(0x0E); //....***.
	LCD_Write(0x04); //.....*..
	LCD_Write(0x00); //........

	//Battery Full
	PORTC = _BV(6) | _BV(4); //Set CGRAM 0x02
	pulse_E();
	delay_ns(1);

	LCD_Write(0x0E); //....***.
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x00); //........

	//Battery 80% Full
	PORTC = _BV(6) | _BV(4) | _BV(3); //Set CGRAM 0x03
	pulse_E();
	delay_ns(1);

	LCD_Write(0x0E); //....***.
	LCD_Write(0x1F); //...*****
	LCD_Write(0x11); //...*...*
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x00); //........

	//Battery 60% Full
	PORTC = _BV(6) | _BV(5); //Set CGRAM 0x04
	pulse_E();
	delay_ns(1);

	LCD_Write(0x0E); //....***.
	LCD_Write(0x1F); //...*****
	LCD_Write(0x11); //...*...*
	LCD_Write(0x11); //...*...*
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x00); //........

	//Battery 40% Full
	PORTC = _BV(6) | _BV(5) | _BV(3); //Set CGRAM 0x05
	pulse_E();
	delay_ns(1);

	LCD_Write(0x0E); //....***.
	LCD_Write(0x1F); //...***** 
	LCD_Write(0x11); //...*...*
	LCD_Write(0x11); //...*...*
	LCD_Write(0x11); //...*...*
	LCD_Write(0x1F); //...*****
	LCD_Write(0x1F); //...*****
	LCD_Write(0x00); //........

	//Battery 20% Full
	PORTC = _BV(6) | _BV(5) | _BV(4); //Set CGRAM 0x06
	pulse_E();
	delay_ns(1);

	LCD_Write(0x0E); //....***.
	LCD_Write(0x1F); //...***** 
	LCD_Write(0x11); //...*...* 
	LCD_Write(0x11); //...*...* 
	LCD_Write(0x11); //...*...* 
	LCD_Write(0x11); //...*...* 
	LCD_Write(0x1F); //...***** 
	LCD_Write(0x00); //........

}

void BatteryLevel(void)
{
    Goto(0x13);

	read_voltage();

   if (voltage <= 1500)
   		LCD_Write(0x06);
	
	if(voltage > 1500 && voltage <= 1800)
		LCD_Write(0x05);

	if(voltage > 1800 && voltage <= 2100)
		LCD_Write(0x04);

	if(voltage > 2100 && voltage <= 2400)
		LCD_Write(0x03); 
	
	if(voltage > 2400)
		LCD_Write(0x02); 
}

void LCD_init(void) //Initialize the LCD
{
	DDRD |= _BV(RS) | _BV(RW) | _BV(E) | _BV(BCKLT); //Set OUTPUT

	PORTA |= _BV(UpArrow) | _BV(DownArrow) | _BV(Back) | _BV(Enter); //Initialize the Pushbuttons

	PORTA &= ~_BV(TemperatureSensor) & ~_BV(BatteryVoltageSensor); //Initialize the Sensors

	DDRC = 0xFF; //Set Port C to be OUTPUT

	delay(255); //wait 26 ms for Vdd rise to 4.5 V
	delay(255); //wait another 26 ms

	PORTD |= _BV(BCKLT); //Turn on LCD Backlight

	PORTD &= ~_BV(RS) & ~_BV(RW) & ~_BV(E); //Set RS, R/W, E to Low

	delay_ns(1); //Wait 100 ns

	PORTC = _BV(5) | _BV(4) | _BV(3); //Function set 8-bit bus

	pulse_E();

	delay(20); //Wait 2 ms

	PORTC = _BV(0); //Clear screen

	pulse_E();

	delay(20); //Wait 2 ms

	PORTC = _BV(1); //Return Home

	pulse_E();

	delay(20); //Wait 2 ms

	PORTC = _BV(2) | _BV(1); //Entry Mode Set

	pulse_E();

	delay_ns(1);

	PORTC = _BV(3) | _BV(2); //Hide Cursor (Set PC1 = 1 to show cursor)

	pulse_E();

	delay_ns(1);

	CharacterGenerate(); //Generate customized characters 

	PORTC = 0x80; //Set DDRAM 0x00 1st char on 1st line

	pulse_E();

}
